/* MQTT (over TCP) Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/

#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"

#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"

#include "esp_log.h"
#include "mqtt_client.h"
#include "os.h"

#include "cJSON.h"

#include "user_mqtt.h"
#include "aliyun_ota.h"
#include "hmi.h"


static const char *TAG = "MQTT_EXAMPLE";

/*
 *	����Ϊ��������Ϣ���ã�����ESP32�밢����ȡ������
 */

/*Broker Address��${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com*/
#define   Aliyun_host       "iot-06z00c3u82mzezw.mqtt.iothub.aliyuncs.com"
#define   Aliyun_port       1883
/*Client ID��     ${ClientID}|securemode=${Mode},signmethod=${SignMethod}|*/
#define   Aliyun_client_id  "h69tvsSgWA3.ESP32-DevKitC|securemode=2,signmethod=hmacsha256,timestamp=1651310639516|"
/*User Name��     ${DeviceName}&${ProductKey}*/
#define   Aliyun_username   "ESP32-DevKitC&h69tvsSgWA3"
/*ʹ�ù��� MQTT_Password ��������*/
#define   Aliyun_password   "8381367c0d5d89f794403802fdfacdb697ce4fcbf65d835ba9b31f70b17efd4d"


#define   AliyunSubscribeTopic_user_get     "/h69tvsSgWA3/ESP32-DevKitC/user/get"
#define   AliyunPublishTopic_user_update    "/h69tvsSgWA3/ESP32-DevKitC/user/update"
#define   AliyunSubscribeTopic_ota_upgrade  "/ota/device/upgrade/h69tvsSgWA3/ESP32-DevKitC"
#define   AliyunPublishTopic_ota_inform     "/ota/device/inform/h69tvsSgWA3/ESP32-DevKitC"

char local_data_buffer[1024] = {0};  


char mqtt_publish_data1[] = "mqtt connect ok ";
char mqtt_publish_data2[] = "mqtt subscribe successful";
char mqtt_publish_data3[] = "mqtt i am esp32";

esp_mqtt_client_handle_t client;
user_aliyun_ota_config_t aliyun_ota_config;



static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
{
    esp_err_t ret;

    esp_mqtt_client_handle_t client = event->client;
    int  msg_id;
	uint8_t temp;
	
	
    // your_context_t *context = event->context;
    switch (event->event_id) {
        case MQTT_EVENT_CONNECTED:
            ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
            msg_id = esp_mqtt_client_publish(client, AliyunPublishTopic_user_update, mqtt_publish_data1, strlen(mqtt_publish_data1), 1, 0);
            ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);

            msg_id = esp_mqtt_client_subscribe(client, AliyunSubscribeTopic_user_get, 0);
            ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);

            break;
        case MQTT_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
            break;

        case MQTT_EVENT_SUBSCRIBED:
            ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
            msg_id = esp_mqtt_client_publish(client, AliyunPublishTopic_user_update, mqtt_publish_data2, strlen(mqtt_publish_data2), 0, 0);
            ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
            break;
        case MQTT_EVENT_UNSUBSCRIBED:
            ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
            break;
        case MQTT_EVENT_PUBLISHED:
            ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
            break;
        case MQTT_EVENT_DATA:
            ESP_LOGI(TAG, "MQTT_EVENT_DATA");
            printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
            printf("DATA=%.*s\r\n", event->data_len, event->data);

            ESP_LOGI(TAG, "this is fifth time!");
           
			temp = strncmp(event->topic, AliyunSubscribeTopic_ota_upgrade, event->topic_len);//�ж������Ƿ���OTA���⣬����ǲŵ���OTA��JSON��������

		    if(0 == temp)//��OTA��������
		    {	
		    	ESP_LOGI(TAG, "OTA DATA PARSE");
		        //char  *strncpy(char *s2, const char *s1, size_t n);����strncpy��s1ָ�����������ิ��n���ַ��������ƿ��ַ�������ַ�����s2ָ��������С�
				strncpy(local_data_buffer, event->data, event->data_len); //��ָ�����͵����ݸ��Ƶ�һ��������
				//printf("local_data_buffer:%s ", local_data_buffer); 
			    ret = user_parse_json(local_data_buffer,aliyun_ota_config);//�������ݣ���ʹ�ý���������URL����OTA������
				if (ret == ESP_OK) //����������OTA�������ɹ�
				{
			        //����JSON��ʽ���ݣ����������ڷ�����������������ƽ̨��������֪ͨ�������������
					cJSON *Wroot =	cJSON_CreateObject();
					cJSON *Pitem =	cJSON_CreateObject();
					
					cJSON_AddItemToObject(Wroot, "id", cJSON_CreateString("123"));
					cJSON_AddItemToObject(Wroot, "params", Pitem);
					cJSON_AddItemToObject(Pitem, "step", cJSON_CreateString("100"));
					cJSON_AddItemToObject(Pitem, "desc", cJSON_CreateString("OTA update successfully !"));
					cJSON_AddItemToObject(Pitem, "module", cJSON_CreateString("ESP32"));

					//beep x4	OTA���³ɹ�
					hmi_beep_on();
					usleep(50*1000);
					hmi_beep_off();
					usleep(50*1000);
					hmi_beep_on();
					usleep(50*1000);
					hmi_beep_off();
					usleep(50*1000);
					hmi_beep_on();
					usleep(50*1000);
					hmi_beep_off();
					usleep(50*1000);
					hmi_beep_on();
					usleep(50*1000);
					hmi_beep_off();
					usleep(50*1000);

				
					//printf("%s\n", cJSON_Print(Wroot)); //��ӡ�ղŹ�����JSON���ݣ����Ƿ���ȷ

					char ota_inform_buf[512];
					int len = strlen(cJSON_Print(Wroot));					
					memcpy(ota_inform_buf, cJSON_Print(Wroot),len); //��JSON��ʽ���ݸ��Ƶ������У������������ʽ���ݸ���������
					ota_inform_buf[len] = '\0';
					printf("%s\n",ota_inform_buf);//��ӡ�����Ƿ���ȷ
					//������Ϣ��������������ƽ̨
		            msg_id = esp_mqtt_client_publish(client, AliyunPublishTopic_ota_inform, ota_inform_buf, strlen(ota_inform_buf), 0, 0);
		            ESP_LOGI(TAG, "sent publish ota inform successful, msg_id=%d", msg_id);		
					
					esp_restart();  //ESP32�豸������������ִ�иղ����صĳ���
				} 
				else 
				{
					ESP_LOGE(TAG, "Firmware upgrade failed");
			    }	


		    }
		    //free(topicBuf);
            break;
        case MQTT_EVENT_ERROR:
            ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
            break;
        default:
            ESP_LOGI(TAG, "Other event id:%d", event->event_id);
            break;
    }
    return ESP_OK;
}




static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
    mqtt_event_handler_cb(event_data);

}



void user_mqtt_app_start(void)
{
	ESP_LOGI(TAG, "111");
	ESP_LOGI(TAG, "222");
    esp_mqtt_client_config_t mqtt_cfg = {
		.host = Aliyun_host,
		.port = Aliyun_port,
		.client_id = Aliyun_client_id,
		.username = Aliyun_username,
		.password = Aliyun_password,

    };

    client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
    esp_mqtt_client_start(client);
	
}

